﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.Serialization;
using TEL.ClientClasses;
using TEL.TelPhoneF.Dialogs;
using TEL.TelPhoneF.InfoList;

namespace TEL.TelPhoneF.Controls
{
    public partial class DataListHistory : TEL.TelPhoneF.Controls.DataListCustom
    {
        private List<ContactCall> HistoryList;
        private List<Contact> ContactsList;
        private List<MissingCall> MissingList;
        private object mLock = new object();
        private object mViewLock = new object();

        private ListViewGroup HistoryGroup;
        private ListViewGroup ContactGroup;
        private ListViewGroup MissingGroup;
        public DataListHistory()
        {
            InitializeComponent();
            txtSearch.BackColor = Form1.BlueSkinColor;
            txtSearch.ForeColor = Color.White;
            
            //dataList.BackColor = Form1.BlueSkinColor;
            try
            {
                DeSerializeList(Properties.Settings.Default.CallHistory.Trim());
                DeSerializeContact(Properties.Settings.Default.Contacts.Trim());
                DeSerializeMissing(Properties.Settings.Default.Missings.Trim());


                MissingGroup = new ListViewGroup("Пропущенные");
                dataList.Groups.Add(MissingGroup);

                HistoryGroup = new ListViewGroup("Звонки");
                dataList.Groups.Add(HistoryGroup);

                ContactGroup = new ListViewGroup("Контакты");
                dataList.Groups.Add(ContactGroup);
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory constructor ", error, false));
            }

        }

        public event EventHandler<BoolEventArgs> MissingViewChanged;

        public void MissingView()
        {
            if (MissingList != null)
                (from q in MissingList where q.IsView select q).ToList().ForEach(x => x.IsView = false);
           SaveMissing();
        }

        public void OnMissingViewChanged()
        {
            bool view = false;
            if (MissingList != null)
                view = (from q in MissingList where q.IsView select q).Count() > 0;

            if (MissingViewChanged != null) MissingViewChanged(this, new BoolEventArgs(view));
        }

        public override bool Vid
        {
            get
            {
                return base.Vid;
            }
            set
            {
                base.Vid = value;
                if (value )
                {
                    Filter = ContactCallState.Entity;
                    ViewHistory();
                }
            }
        }

        private ContactCallState m_filter = ContactCallState.Missing;
        public ContactCallState Filter
        {
            get { return m_filter; }
            set
            {
                if (m_filter != value)
                {
                    m_filter = value;

                    btnFilterAll.State = false;
                    btnFilterMissing.State = false;
                    btnFilterAccepted.State = false;
                    btnFilterOut.State = false;
                    switch (value)
                    {
                        case ContactCallState.Accepted :
                            btnFilterAccepted.State = true;
                            break;
                        case ContactCallState.Entity:
                            btnFilterAll.State = true;
                            break;
                        case ContactCallState.Missing:
                            btnFilterMissing.State = true;
                            break;
                        case ContactCallState.Out:
                            btnFilterOut.State = true;
                            break;
                    }

                    ViewHistory();
                }
            }
        }

        private string m_searchData = string.Empty;
        public string SearchData
        {
            get { return m_searchData; }
            set
            {
                if (m_searchData != value)
                {
                    m_searchData = value;
                    ViewHistory();
                }
            }
        }

        private List<Contact> ViewList()
        {
            List<Contact> res = new List<Contact>();
            HistoryList.Sort(new Comparison<ContactCall>((a, b) => b.Date.CompareTo(a.Date)));
            MissingList.Sort(new Comparison<ContactCall>((a, b) => b.Date.CompareTo(a.Date)));
            res.AddRange(MissingList);
            res.AddRange(HistoryList);
            res.AddRange(ContactsList);
            return res;
        }

        private void ViewHistory()
        {
            if (!Vid) return;
            BeginUpdate();
            try
            {
                System.Threading.Monitor.Enter(mViewLock);
                ClearList();
                List<Contact> filterList =
                    (from x in ViewList()
                     where x.Check(m_filter, m_searchData)
                     select x).ToList();

                foreach (Contact item in filterList)
                {
                    ViewContactHistory(item);
                }
            }
            catch (Exception)
            {
            }
            finally
            {
                System.Threading.Monitor.Exit(mViewLock);
            }
            EndUpdate();
        }

        public Contact FindFirstContact(string searchKey)
        {
            Contact res = null;
            try
            {
                List<Contact> filterList =
                    (from x in ViewList()
                     where x.FindByPhone(searchKey)
                     select x).ToList();
                res = filterList.Count == 0 ? null : filterList[0];
                if (res == null)
                {
                    filterList =
                        (from x in ViewList()
                         where x.FindByName(searchKey)
                         select x).ToList();
                    res = filterList.Count == 0 ? null : filterList[0];
                }
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory FindFirstContact  -  " + searchKey, error, false));
            }
            return res;
        }

        public string FindNameByPhone(string phone)
        {
            try
            {
                List<Contact> filterList =
                    (from x in ViewList()
                     where x.ContactPhone == phone && !string.IsNullOrEmpty(x.ContactName)
                     select x).ToList();
                return filterList.Count == 0 ? string.Empty : filterList[0].ContactName;
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory FindNameByPhone  -  " + phone, error, false));
                return string.Empty;
            }
        }

        public string SerializeContact()
        {
            try
            {
                MemoryStream memoryStream = new MemoryStream();
                XmlSerializer serializer = new XmlSerializer(typeof(List<InfoList.Contact>));
                serializer.Serialize(memoryStream, ContactsList);
                UTF8Encoding encoding = new UTF8Encoding();
                string vertexXml = encoding.GetString(memoryStream.ToArray());
                return vertexXml;
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory SerializeContact ", error, false));
                return string.Empty;
            }
        }

        public void DeSerializeContact(string data)
        {
            try
            {
                if (string.IsNullOrEmpty(data))
                {
                    ContactsList = new List<Contact>();
                    return;
                }
                UTF8Encoding encoding = new UTF8Encoding();
                Byte[] byteArray = encoding.GetBytes(data);
                MemoryStream memoryStream = new MemoryStream(byteArray);
                XmlSerializer serializer = new XmlSerializer(typeof(List<InfoList.Contact>));
                ContactsList = new List<InfoList.Contact>((List<InfoList.Contact>)serializer.Deserialize(memoryStream));
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory DeSerializeContact ", error, false));
            }
        }

        public void DeSerializeMissing(string data)
        {
            try
            {

                if (string.IsNullOrEmpty(data))
                {
                    MissingList = new List<MissingCall>();
                    OnMissingViewChanged();
                    return;
                }
                UTF8Encoding encoding = new UTF8Encoding();
                Byte[] byteArray = encoding.GetBytes(data);
                MemoryStream memoryStream = new MemoryStream(byteArray);
                XmlSerializer serializer = new XmlSerializer(typeof(List<MissingCall>));
                MissingList = new List<MissingCall>((List<MissingCall>)serializer.Deserialize(memoryStream));
                OnMissingViewChanged();
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory DeSerializeMissing ", error, false));
            }
        }

        public string SerializeMissing()
        {
            try
            {
                MemoryStream memoryStream = new MemoryStream();
                XmlSerializer serializer = new XmlSerializer(typeof(List<MissingCall>));
                serializer.Serialize(memoryStream, MissingList);
                UTF8Encoding encoding = new UTF8Encoding();
                string vertexXml = encoding.GetString(memoryStream.ToArray());
                return vertexXml;
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory SerializeMissing ", error, false));
                return string.Empty;
            }
        }

        public string SerializeList()
        {
            try
            {
                MemoryStream memoryStream = new MemoryStream();
                XmlSerializer serializer = new XmlSerializer(typeof(List<ContactCall>));
                serializer.Serialize(memoryStream, HistoryList);
                UTF8Encoding encoding = new UTF8Encoding();
                string vertexXml = encoding.GetString(memoryStream.ToArray());
                return vertexXml;
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory SerializeList ", error, false));
                return string.Empty;
            }
        }

        public void DeSerializeList(string data)
        {
            try
            {
                if (string.IsNullOrEmpty(data))
                {
                    HistoryList = new List<ContactCall>();
                    return;
                }
                UTF8Encoding encoding = new UTF8Encoding();
                Byte[] byteArray = encoding.GetBytes(data);
                MemoryStream memoryStream = new MemoryStream(byteArray);
                XmlSerializer serializer = new XmlSerializer(typeof(List<ContactCall>));
                HistoryList = new List<ContactCall>((List<ContactCall>)serializer.Deserialize(memoryStream));
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory DeSerializeList ", error, false));
            }
        }

        protected override void SaveList()
        {
            try
            {
                Properties.Settings.Default.CallHistory = HistoryList.Count > 0 ? SerializeList() : string.Empty;
                Properties.Settings.Default.Save();
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory SaveList ", error, false));
            }
        }

        protected void SaveContact()
        {
            try
            {
                ContactsList.Sort(new Comparison<Contact>((a, b) =>
                                                              {
                                                                  int f = b.Favorite.CompareTo(a.Favorite);
                                                                  if (f != 0) return f;
                                                                  return a.ContactName.CompareTo(b.ContactName);
                                                              }));
                Properties.Settings.Default.Contacts = SerializeContact();
                Properties.Settings.Default.Save();
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory SaveContact ", error, false));
            }
        }

        protected void SaveMissing()
        {
            try
            {
                MissingList.Sort(new Comparison<MissingCall>((a, b) => a.MissingCount.CompareTo(b.MissingCount)));
                Properties.Settings.Default.Missings = SerializeMissing();
                Properties.Settings.Default.Save();
                OnMissingViewChanged();
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory SaveMissing ", error, false));
            }
        }
        private void AddContact(Contact contact)
        {
            if (!string.IsNullOrEmpty(contact.ContactName))
            {
                IEnumerable<Contact> c = from q in ContactsList
                                         where q.ContactPhone == contact.ContactPhone
                                         select q;
                if (c.Count() == 0)
                    ContactsList.Add(new Contact()
                                         {
                                             ContactName = contact.ContactName,
                                             ContactPhone = contact.ContactPhone
                                         });
                else c.First().ContactName = contact.ContactName;
                SaveContact();
            }
        }

        private void AddMissing(MissingCall missingCall)
        {
            IEnumerable<MissingCall> mList = from q in MissingList
                                             where q.ContactPhone == missingCall.ContactPhone
                                             select q;
            if (mList.Count() == 0)
            {
                missingCall.MissingCount = 1;
                MissingList.Add(missingCall);
            }
            else
            {
                MissingCall mc = mList.First();
                mc.Date = missingCall.Date;
                mc.MissingCount++;
            }
            SaveMissing();
        }

        public void AddCallHistory(ContactCall contactCall)
        {
            try
            {
                System.Threading.Monitor.Enter(mLock);
                if (string.IsNullOrEmpty(contactCall.ContactName))
                    contactCall.ContactName = FindNameByPhone(contactCall.ContactPhone);

                AddContact(contactCall);
                MissingCall missingCall = contactCall as MissingCall;
                if (missingCall != null) AddMissing(missingCall);

                if (HistoryList == null) HistoryList = new List<ContactCall>();

                if ((from q in HistoryList where q.Date == contactCall.Date select q).Count() == 0)
                {
                    HistoryList.Add(contactCall);
                    if (HistoryList.Count > 50) HistoryList.RemoveAt(0);
                    SaveList();
                }
               
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory AddCallHistory ", error, false));
            }
            finally
            {
                System.Threading.Monitor.Exit(mLock);
            }
            ViewHistory();
        }

        public void UpdateStateHistory(DateTime dateTime, ContactCallState state)
        {
            try
            {
                System.Threading.Monitor.Enter(mLock);
                if (HistoryList == null) throw new ArgumentNullException("HistoryList");

                ContactCall contactCall = (from q in HistoryList where q.Date == dateTime select q).First();
                contactCall.State = state;
                SaveList();
                
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory UpdateStateHistory ", error, false));
            }
            finally
            {
                System.Threading.Monitor.Exit(mLock);
            }
            ViewHistory();
        }

        private void ViewContactHistory(Contact contact)
        {
            ListViewItem item = new ListViewItem();
            item.Text = contact.ContactPhone;
            
            ContactCall contactCall = contact as ContactCall;
            if (contactCall != null)
            {
                MissingCall missingCall = contact as MissingCall;
                if (missingCall != null)
                {
                    if (missingCall.MissingCount > 1)
                        item.SubItems.Add(string.Format("{0} ({1})", contact.ContactName, missingCall.MissingCount));
                    else
                        item.SubItems.Add(contact.ContactName);

                    item.Group = MissingGroup;
                }
                else
                {
                    item.SubItems.Add(contact.ContactName);
                    item.Group = HistoryGroup;
                }
            //   string s =  contactCall.Date.ToString("{0:yyyy.MM.dd HH:mm:ss}");
                item.SubItems.Add(string.Format("{0:yyyy.MM.dd HH:mm:ss}", contactCall.Date));
                item.ImageIndex = (int)contactCall.State;
            }
            else
            {
                item.SubItems.Add(contact.ContactName);
                item.Group = ContactGroup;
                item.ImageIndex = 3;
                
            }
            
            item.Tag = contact;
            ListItemAdd(item);

        }

        private void DataListHistory_Load(object sender, EventArgs e)
        {
            ViewHistory();
        }

        public void DeleteMissing(string phone)
        {
            try
            {
                if (string.IsNullOrEmpty(phone)) MissingList.Clear();
                else
                {
                    MissingList.RemoveAll(x => x.ContactPhone == phone);
                }
                SaveMissing();
                ViewHistory();
               
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory DeleteMissing ", error, false));
            }
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            try
            {
                System.Threading.Monitor.Enter(mLock);
                HistoryList.RemoveAll(x => x.Check(m_filter, m_searchData));
                SaveList();
               
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory btnClear_Click ", error, false));
            }
            finally
            {
                System.Threading.Monitor.Exit(mLock);
            }
            ViewHistory();
        }

        private void btnFilterAll_Click(object sender, EventArgs e)
        {
            try
            {
                Filter = ContactCallState.Entity;
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory btnFilterAll_Click ", error, false));
            }
        }

        private void btnFilterOut_Click(object sender, EventArgs e)
        {
            try
            {
                Filter = ContactCallState.Out;
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory btnFilterOut_Click ", error, false));
            }

        }

        private void btnFilterAccepted_Click(object sender, EventArgs e)
        {
            try
            {
                Filter = ContactCallState.Accepted;
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory btnFilterAccepted_Click ", error, false));
            }
        }

        private void btnFilterMissing_Click(object sender, EventArgs e)
        {
            try
            {
                Filter = ContactCallState.Missing;
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory btnFilterMissing_Click ", error, false));
            }
        }

        protected override void txtSearch_TextChanged(object sender, EventArgs e)
        {
            try
            {
                SearchData = txtSearch.Text;
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory txtSearch_TextChanged ", error, false));
            }

        }

        public event EventHandler<StringEventArgs> HistoryCall;

        protected override void dataList_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            try
            {
                if (dataList.SelectedItems.Count == 0) return;

                Contact contactCall = dataList.SelectedItems[0].Tag as Contact;
                if (contactCall != null && HistoryCall != null)
                {
                    HistoryCall(this, new StringEventArgs(contactCall.ContactPhone));
                }
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory dataList_MouseDoubleClick ", error, false));
            }
        }

        private void SetCallNameByContact(Contact contact)
        {
            try
            {
                (from q in HistoryList where q.ContactPhone == contact.ContactPhone select q).ToList().ForEach(x => x.ContactName = contact.ContactName);
                SaveList();
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory SetCallNameByContact ", error, false));
            }

        }

        private void miAddContact_Click(object sender, EventArgs e)
        {
            int i = 0;
            try
            {
                Contact contact = new Contact();

                if (dataList.SelectedItems.Count > 0)
                {
                    ContactCall contactCall = dataList.SelectedItems[0].Tag as ContactCall;
                    if (contactCall != null && string.IsNullOrEmpty(contactCall.ContactName)
                        && dataList.SelectedItems[0].Group.Header == "Звонки")
                        contact = contactCall;
                }
                Dialogs.DialogContact dialogContact = new DialogContact() { SourceObject = contact, DialigType = DialogType.Add };
                if (dialogContact.ShowDialog() == DialogResult.OK)
                {
                    AddContact(contact);
                    SetCallNameByContact(contact);
                    ViewHistory();

                    try
                    {
                        i = (from q in ContactGroup.Items.Cast<ListViewItem>() where q.Text == contact.ContactPhone select q).First().Index;
                        dataList.EnsureVisible(i);
                        dataList.Items[i].Selected = true;
                    }
                    catch (Exception)
                    { }
                }
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory miAddContact_Click ", error, false));
            }
        }

        private void miEditContact_Click(object sender, EventArgs e)
        {
            int i = 0;
            try
            {
                if (dataList.SelectedItems.Count > 0)
                {
                    ListViewItem item = dataList.SelectedItems[0];
                    Contact contact = item.Tag as Contact;
                    if (contact != null && item.Group.Header == "Контакты")
                    {
                        Dialogs.DialogContact dialogContact = new DialogContact() { SourceObject = contact, DialigType = DialogType.Edit };
                        if (dialogContact.ShowDialog() == DialogResult.OK)
                        {
                            SaveContact();
                            SetCallNameByContact(contact);
                            ViewHistory();

                            try
                            {
                                i =
                                    (from q in ContactGroup.Items.Cast<ListViewItem>() where q.Text == contact.ContactPhone select q).First().
                                        Index;
                                dataList.EnsureVisible(i);
                                dataList.Items[i].Selected = true;
                            }
                            catch (Exception)
                            { }
                        }
                    }
                }
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory miEditContact_Click ", error, false));
            }
        }

        private void miDeleteContact_Click(object sender, EventArgs e)
        {
            try
            {
                if (dataList.SelectedItems.Count > 0)
                {
                    string groupHeader = string.Empty;
                    ListViewItem item = dataList.SelectedItems[0];
                    Contact contact = item.Tag as Contact;
                    if (contact == null) return;

                    Dialogs.DialogContact dialogContact = new DialogContact() { SourceObject = contact, DialigType = DialogType.Delete };
                    if (dialogContact.ShowDialog() == DialogResult.OK)
                    {
                        groupHeader = dataList.SelectedItems[0].Group.Header;
                        switch (groupHeader)
                        {
                            case "Звонки":
                                HistoryList.RemoveAll(x => x.ContactPhone == contact.ContactPhone);
                                SaveList();
                                break;
                            case "Контакты":
                                ContactsList.RemoveAll(x => x.ContactPhone == contact.ContactPhone);
                                SaveContact();
                                break;
                            case "Пропущенные":
                                MissingList.RemoveAll(x => x.ContactPhone == contact.ContactPhone);
                                SaveMissing();
                                
                                break;
                        }
                        ViewHistory();
                    }
                }
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory miDeleteContact_Click ", error, false));
            }
        }

        private void dataList_MouseClick(object sender, MouseEventArgs e)
        {
            try
            {
                if (e.Button == MouseButtons.Right)
                {
                    string groupHeader = string.Empty;
                    if (dataList.SelectedItems.Count > 0)
                        groupHeader = dataList.SelectedItems[0].Group.Header;

                    switch (groupHeader)
                    {
                        case "Звонки":
                            miEditContact.Visible = false;
                            miFavorite.Visible = false;
                            break;
                        case "Контакты":
                            miEditContact.Visible = true;
                            miFavorite.Visible = true;
                            if (dataList.SelectedItems.Count > 0)
                            {
                                ListViewItem item = dataList.SelectedItems[0];
                                Contact contact = item.Tag as Contact;
                               if (contact != null)
                                miFavorite.Text = contact.Favorite ? "Удалить из избранных" : "Добавить в избранные";
                               else miFavorite.Visible = false;
                            }
                            break;
                        case "Пропущенные":
                            miEditContact.Visible = false;
                            miFavorite.Visible = false;
                            break;
                    }
                }
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory dataList_MouseClick ", error, false));
            }
        }

        private void btnClearMissing_Click(object sender, EventArgs e)
        {
            try
            {
                DeleteMissing(string.Empty);
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory btnClearMissing_Click ", error, false));
            }
        }

        private void miFavorite_Click(object sender, EventArgs e)
        {
            try
            {
                int i = 0;
                if (dataList.SelectedItems.Count > 0)
                {
                    ListViewItem item = dataList.SelectedItems[0];
                    Contact contact = item.Tag as Contact;
                    if (contact != null && item.Group.Header == "Контакты")
                    {
                        string s = item.Text;
                        contact.Favorite = !contact.Favorite;
                        SaveContact();
                        //   SetCallNameByContact(contact);
                        ViewHistory();
                        try
                        {
                            i =
                                (from q in ContactGroup.Items.Cast<ListViewItem>() where q.Text == s select q).First().
                                    Index;
                            dataList.EnsureVisible(i);
                            dataList.Items[i].Selected = true;
                        }
                        catch (Exception)
                        {}
                    }
                }
            }
            catch (Exception error)
            {
                OnErrorEvent(new StrErrorEventArgs("DataListHistory miEditContact_Click ", error, false));
            }
        }

        private void dataList_ColumnReordered(object sender, ColumnReorderedEventArgs e)
        {

        }

        public int HistoryWidth()
        {
            
            int res = 20;
            foreach (ColumnHeader item in dataList.Columns)
            {
                res += item.Width;
            }
            return res;
        }

        public event EventHandler WidthChanged;
        private void dataList_ColumnWidthChanged(object sender, ColumnWidthChangedEventArgs e)
        {
            if (WidthChanged != null) WidthChanged(this, EventArgs.Empty);
        }

       
    }
}
